﻿namespace EasyToolkit.BindingTemplates.Context
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using EasyToolkit.BindingTemplates.Definitions;
    using EasyToolkit.BindingTemplates.Definitions.Binding;
    using EasyToolkit.BindingTemplates.SortAndFilter;
    using System.Threading.Tasks;

    class BindingContextElement : IBindingContextElement
    {
        private bool disposed;

        public IBindingContext Parent
        { get; private set; }

        public object DataSource
        { get; private set; }

        public int Index
        { get; private set; }

        public List<IBindingContextItem> BindingContextItems
        { get; private set; }

        public List<IBindingContext> LinkedBindingContexts
        { get; private set; }

        public object Element
        { get; private set; }

        #region .ctors
        public BindingContextElement(IBindingContext parent, object dataSource, Dictionary<ITemplateDefinition, ISortAndFilter> sortsAndFilters, int index)
        {
            BindingContextItems = new List<IBindingContextItem>();
            LinkedBindingContexts = new List<IBindingContext>();

            Parent = parent;
            DataSource = dataSource;
            Index = index;

            Init(sortsAndFilters);
        }

        ~BindingContextElement()
        {
            Dispose();
        }
        #endregion

        #region private method
        private void Init(Dictionary<ITemplateDefinition, ISortAndFilter> sortsAndFilters)
        {
            try
            {
                if (Parent.SortAndFilter != null)
                    Element = Activator.CreateInstance(Parent.TemplateDefinition.BindingType.BindType);

                foreach (IBindingDefinition bindingDefinition in Parent.TemplateDefinition.BindingDefinitions)
                {
                    if (bindingDefinition != null)
                    {
                        IBindingContextItem item = bindingDefinition.ContextItemFactory(this);
                        BindingContextItems.Add(item);                        
                    }
                }
////#if DEBUG
                LinkedBindingContexts = new List<IBindingContext>();
                foreach (ILinkedTemplateDefinition lt in Parent.TemplateDefinition.LinkedTemplates)
                {
                    object resolvedBinding = lt.ResolveBinding(DataSource);
                    BindingContext linkedContext = new BindingContext(this, lt.TemplateDefinition, resolvedBinding, sortsAndFilters, Index);
                    LinkedBindingContexts.Add(linkedContext);
                }
////#else
                //IBindingContext[] contexts = new IBindingContext[Parent.TemplateDefinition.LinkedTemplates.Count];
                //if (contexts.Count() > 0)
                //{
                //    Parallel.For(0, Parent.TemplateDefinition.LinkedTemplates.Count, i =>
                //    {
                //        ILinkedTemplateDefinition lt = Parent.TemplateDefinition.LinkedTemplates[i];
                //        object resolvedBinding = lt.ResolveBinding(DataSource);
                //        contexts[i] = new BindingContext(this, lt.TemplateDefinition, resolvedBinding, sortsAndFilters, Index);
                //    });
                //}
                //LinkedBindingContexts = contexts.ToList();
//#endif
            }
            catch (Exception ex)//@@
            {
                throw ex;
            }
        }
        #endregion

        #region public method
        public void Dispose()
        {
            if (!disposed)
            {
                disposed = true;
                foreach (IBindingContextItem part in BindingContextItems)
                    part.Dispose();
                BindingContextItems.Clear();

                foreach (IBindingContext part in LinkedBindingContexts)
                    part.Dispose();
                LinkedBindingContexts.Clear();
            }
        }
        #endregion
    }
}
